package com.huzz.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huzz.entity.*;
import com.huzz.model.RegisterModel;
import com.huzz.service.*;
import com.huzz.util.entityutil.ModelUtil;
import com.huzz.vo.MenuVO;
import com.huzz.vo.SysUserVO;
import com.huzz.util.body.DataBox;
import com.huzz.util.encryption.RSAUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Name 名称
 * @Description 描述
 * @Author 童年的纸飞机
 * @Since 2023-04-2023/4/25 16:25
 */
@Service
public class SaTokenServiceImpl implements SaTokenService {

    @Value("${encryption.rsa.publicKey}")
    private String publicKey;

    @Value("${encryption.rsa.privateKey}")
    private String privateKey;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysSecondAuthService secondAuthService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysPermissionService permissionService;

    @Autowired
    private ISysMenuService menuService;

    @Override
    public DataBox<Object> login(LoginModel loginModel) {
        // TODO 验证码
        // 身份校验
        SysUser sysUser = userService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, loginModel.getUsername()));
        if (ObjectUtils.isEmpty(sysUser)) {
            return DataBox.failedBuilder("用户名输入错误或未注册");
        }
        if (!RSAUtils.verification(loginModel.getPassword(), sysUser.getPassword(), privateKey)) {
            return DataBox.failedBuilder("密码输入错误");

        }
        // 是否被封禁
        StpUtil.checkDisable(sysUser.getId());
        // 登录
        StpUtil.login(sysUser.getId(), loginModel.isRememberMe());

        return DataBox.succeedBuilder(StpUtil.getTokenInfo());
    }

    @Override
    public DataBox<String> openSafe(String service, String secondPassword) {
        if (StringUtils.isEmpty(service) || StringUtils.isEmpty(secondPassword)) {
            return DataBox.failedBuilder("业务模块标识和密码不能为空");
        }
        SysSecondAuth secondAuth = secondAuthService.getOne(Wrappers.<SysSecondAuth>lambdaQuery().eq(SysSecondAuth::getService, service));
        if (ObjectUtils.isEmpty(secondAuth)) {
            return DataBox.failedBuilder("业务模块标识填写错误或不存在");
        }
        if (RSAUtils.verification(secondPassword, secondAuth.getSecondPassword(), privateKey)) {
            StpUtil.openSafe(service, secondAuth.getSafeTime());
            return DataBox.succeedBuilder("二级认证通过");
        }
        return DataBox.failedBuilder("密码不正确, 认证不通过");
    }

    @Override
    public DataBox<String> register(RegisterModel registerModel) {
        // TODO 加验证码
        // 验证是否注册过
        if (ObjectUtils.isNotEmpty(userService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, registerModel.getUsername())))) {
            return DataBox.failedBuilder("该用户名已被注册");
        }
        // 密码加密
        registerModel.setPassword(RSAUtils.encryption(registerModel.getPassword(), publicKey));
        // 转换为保存实体
        SysUser sysUser = ModelUtil.transToSimilarEntity(registerModel, SysUser.class);

        return DataBox.builder(userService.save(sysUser), "注册成功", "注册失败");
    }

    @Override
    public DataBox<String> isLogin() {
        return DataBox.builder(StpUtil.isLogin(), "已登录, 当前账号id:" + StpUtil.getLoginIdAsString(), "未登录");
    }

    @Override
    public void logout() {
        StpUtil.logout();
    }

    @Override
    public SaTokenInfo getTokenInfo() {
        return StpUtil.getTokenInfo();
    }

    @Override
    public List<String> getPermissionList() {
        return StpUtil.getPermissionList();
    }

    @Override
    public List<String> getRoleList() {
        return StpUtil.getRoleList();
    }

    @Override
    public String coerceLogout(String value, Long time, String type) {
        String result = "";
        switch (type) {
            case "logout_loginId":
                StpUtil.logout(Integer.valueOf(value));
                result = "已强制所有端下线";
                break;
            case "logout_loginId_PC":
                StpUtil.logout(Integer.valueOf(value), "PC");
                result = "已强制PC端下线";
                break;
            case "logout_loginId_phone":
                StpUtil.login(Integer.valueOf(value), "phone");
                result = "已强制手机端下线";
                break;
            case "logout_token":
                StpUtil.logoutByTokenValue(value);
                result = "已强制该Token所在端下线";
                break;
            case "disable_loginId_time":
                StpUtil.kickout(Integer.valueOf(value));
                StpUtil.disable(Integer.valueOf(value), time);
                result = "已封禁该账号长达" + time + "秒";
                break;
            case "kickout_loginId":
                StpUtil.kickout(Integer.valueOf(value));
                result = "已踢该账号所有端下线";
                break;
            case "kickout_loginId_PC":
                StpUtil.kickout(Integer.valueOf(value), "PC");
                result = "已踢该账号PC端下线";
                break;
            case "kickout_loginId_phone":
                StpUtil.kickout(Integer.valueOf(value), "phone");
                result = "已踢该账号手机端下线";
                break;
            case "kickout_token":
                StpUtil.kickoutByTokenValue(value);
                result = "已踢该Token所在端下线";
                break;
            default:
        }

        return result;
    }

    @Override
    public String getDisableTime(Integer loginId) {
        return StpUtil.getDisableTime(loginId) + "秒";
    }

    @Override
    public JSONObject getCurrentUserInfo() {
        JSONObject result = new JSONObject();

        Object loginId = StpUtil.getLoginId();

        SysUserVO currentUser = userService.getSysUserById(Integer.valueOf((String) loginId));
        result.put("currentUser", currentUser);

        List<SysRole> roleList = roleService.findRoleListByUserId(Integer.valueOf((String) loginId));
        result.put("roleList", roleList);

        List<SysPermission> permissionList = permissionService.findPermissionListByUserId(Integer.valueOf((String) loginId));
        result.put("permissionList", permissionList);

        List<MenuVO> menuVOTreeList = menuService.findMenuVOTreeListByUserId(Integer.valueOf((String) loginId));
        result.put("menuVOTreeList", menuVOTreeList);

        return result;
    }

    @Override
    public void untieDisable(Integer loginId) {
        StpUtil.untieDisable(loginId);
    }
}
